Skip to content

Conversation

@cuiweixie
Copy link
Contributor

benchmark with code:

// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package discover

import (
	"crypto/rand"
	"net"
	"testing"

	"github.com/ethereum/go-ethereum/p2p/enode"
	"github.com/ethereum/go-ethereum/p2p/enr"
)

// BenchmarkTable_findnodeByID benchmarks the findnodeByID function with different
// table sizes and parameters.
func BenchmarkTable_findnodeByID(b *testing.B) {
	benchmarks := []struct {
		name       string
		tableSize  int
		nresults   int
		preferLive bool
		liveRatio  float64 // ratio of live nodes (0.0 to 1.0)
	}{
		{"SmallTable_5Results_NoPreferLive", 50, 5, false, 0.0},
		{"SmallTable_16Results_NoPreferLive", 50, 16, false, 0.0},
		{"SmallTable_5Results_PreferLive_AllLive", 50, 5, true, 1.0},
		{"SmallTable_16Results_PreferLive_AllLive", 50, 16, true, 1.0},
		{"SmallTable_5Results_PreferLive_HalfLive", 50, 5, true, 0.5},
		{"SmallTable_16Results_PreferLive_HalfLive", 50, 16, true, 0.5},
		{"MediumTable_5Results_NoPreferLive", 200, 5, false, 0.0},
		{"MediumTable_16Results_NoPreferLive", 200, 16, false, 0.0},
		{"MediumTable_5Results_PreferLive_AllLive", 200, 5, true, 1.0},
		{"MediumTable_16Results_PreferLive_AllLive", 200, 16, true, 1.0},
		{"MediumTable_5Results_PreferLive_HalfLive", 200, 5, true, 0.5},
		{"MediumTable_16Results_PreferLive_HalfLive", 200, 16, true, 0.5},
		{"LargeTable_5Results_NoPreferLive", 500, 5, false, 0.0},
		{"LargeTable_16Results_NoPreferLive", 500, 16, false, 0.0},
		{"LargeTable_5Results_PreferLive_AllLive", 500, 5, true, 1.0},
		{"LargeTable_16Results_PreferLive_AllLive", 500, 16, true, 1.0},
		{"LargeTable_5Results_PreferLive_HalfLive", 500, 5, true, 0.5},
		{"LargeTable_16Results_PreferLive_HalfLive", 500, 16, true, 0.5},
		{"FullTable_5Results_NoPreferLive", nBuckets * bucketSize, 5, false, 0.0},
		{"FullTable_16Results_NoPreferLive", nBuckets * bucketSize, 16, false, 0.0},
		{"FullTable_5Results_PreferLive_AllLive", nBuckets * bucketSize, 5, true, 1.0},
		{"FullTable_16Results_PreferLive_AllLive", nBuckets * bucketSize, 16, true, 1.0},
	}

	for _, bm := range benchmarks {
		b.Run(bm.name, func(b *testing.B) {
			transport := newPingRecorder()
			tab, db := newTestTable(transport, Config{})
			defer db.Close()
			defer tab.close()

			// Wait for table initialization
			<-tab.initDone

			// Fill table with nodes
			nodes := generateTestNodes(bm.tableSize, tab.self().ID())
			fillTable(tab, nodes, false)

			// Set some nodes as live based on liveRatio
			if bm.preferLive && bm.liveRatio > 0 {
				setNodesLive(tab, nodes, bm.liveRatio)
			}

			// Generate a random target ID once per benchmark run
			target := generateRandomID()

			b.ResetTimer()
			b.ReportAllocs()
			for i := 0; i < b.N; i++ {
				_ = tab.findnodeByID(target, bm.nresults, bm.preferLive)
			}
		})
	}
}

// generateTestNodes creates a slice of test nodes with random IDs.
func generateTestNodes(count int, baseID enode.ID) []*enode.Node {
	nodes := make([]*enode.Node, count)
	for i := 0; i < count; i++ {
		var r enr.Record
		r.Set(enr.IP(net.IP{10, 0, byte(i >> 8), byte(i & 0xFF)}))
		r.Set(enr.UDP(30303))
		// Generate nodes at various distances
		distance := i % 256
		nodeID := idAtDistance(baseID, distance)
		nodes[i] = enode.SignNull(&r, nodeID)
	}
	return nodes
}

// setNodesLive sets a percentage of nodes in the table as live.
func setNodesLive(tab *Table, nodes []*enode.Node, liveRatio float64) {
	tab.mutex.Lock()
	defer tab.mutex.Unlock()

	liveCount := int(float64(len(nodes)) * liveRatio)
	for i := 0; i < liveCount && i < len(nodes); i++ {
		b := tab.bucket(nodes[i].ID())
		for _, n := range b.entries {
			if n.ID() == nodes[i].ID() {
				n.livenessChecks = 1
				n.isValidatedLive = true
				break
			}
		}
	}
}

// generateRandomID generates a random enode.ID for use as a target.
func generateRandomID() enode.ID {
	var id enode.ID
	rand.Read(id[:])
	return id
}

result in:

goos: darwin
goarch: arm64
pkg: github.com/ethereum/go-ethereum/p2p/discover
cpu: Apple M1 Pro
                                                                │    old.txt    │               new.txt                │
                                                                │    sec/op     │    sec/op     vs base                │
Table_findnodeByID/SmallTable_5Results_NoPreferLive-10             370.7n ±  5%   370.6n ±  5%        ~ (p=0.579 n=10)
Table_findnodeByID/SmallTable_16Results_NoPreferLive-10            457.6n ±  5%   447.6n ±  3%        ~ (p=0.128 n=10)
Table_findnodeByID/SmallTable_5Results_PreferLive_AllLive-10       717.9n ±  6%   377.4n ±  9%  -47.43% (p=0.000 n=10)
Table_findnodeByID/SmallTable_16Results_PreferLive_AllLive-10      866.8n ±  4%   460.8n ±  3%  -46.85% (p=0.000 n=10)
Table_findnodeByID/SmallTable_5Results_PreferLive_HalfLive-10      709.5n ±  7%   396.8n ±  7%  -44.08% (p=0.000 n=10)
Table_findnodeByID/SmallTable_16Results_PreferLive_HalfLive-10     857.4n ±  4%   472.6n ±  5%  -44.88% (p=0.000 n=10)
Table_findnodeByID/MediumTable_5Results_NoPreferLive-10            383.4n ± 10%   392.2n ±  6%        ~ (p=0.481 n=10)
Table_findnodeByID/MediumTable_16Results_NoPreferLive-10           465.1n ±  6%   463.2n ±  3%        ~ (p=0.971 n=10)
Table_findnodeByID/MediumTable_5Results_PreferLive_AllLive-10      712.2n ±  6%   380.1n ±  4%  -46.64% (p=0.000 n=10)
Table_findnodeByID/MediumTable_16Results_PreferLive_AllLive-10     842.4n ±  6%   466.6n ±  5%  -44.60% (p=0.000 n=10)
Table_findnodeByID/MediumTable_5Results_PreferLive_HalfLive-10     708.0n ±  6%   398.7n ± 14%  -43.69% (p=0.000 n=10)
Table_findnodeByID/MediumTable_16Results_PreferLive_HalfLive-10    846.7n ±  3%   472.0n ±  9%  -44.25% (p=0.000 n=10)
Table_findnodeByID/LargeTable_5Results_NoPreferLive-10             599.1n ±  5%   593.0n ±  5%        ~ (p=0.436 n=10)
Table_findnodeByID/LargeTable_16Results_NoPreferLive-10            826.8n ±  3%   815.0n ±  2%        ~ (p=0.353 n=10)
Table_findnodeByID/LargeTable_5Results_PreferLive_AllLive-10      1167.0n ±  4%   593.5n ±  3%  -49.14% (p=0.000 n=10)
Table_findnodeByID/LargeTable_16Results_PreferLive_AllLive-10     1602.0n ±  3%   840.6n ±  6%  -47.53% (p=0.000 n=10)
Table_findnodeByID/LargeTable_5Results_PreferLive_HalfLive-10     1050.0n ±  3%   521.0n ±  4%  -50.39% (p=0.000 n=10)
Table_findnodeByID/LargeTable_16Results_PreferLive_HalfLive-10    1375.0n ±  3%   666.5n ±  2%  -51.52% (p=0.000 n=10)
Table_findnodeByID/FullTable_5Results_NoPreferLive-10              555.7n ±  6%   549.6n ± 12%        ~ (p=0.796 n=10)
Table_findnodeByID/FullTable_16Results_NoPreferLive-10             767.8n ±  3%   770.5n ±  2%        ~ (p=0.566 n=10)
Table_findnodeByID/FullTable_5Results_PreferLive_AllLive-10       1061.0n ±  6%   584.9n ±  8%  -44.87% (p=0.000 n=10)
Table_findnodeByID/FullTable_16Results_PreferLive_AllLive-10      1437.5n ±  5%   776.7n ±  1%  -45.97% (p=0.000 n=10)
geomean                                                            774.2n         518.4n        -33.04%

                                                                │  old.txt   │               new.txt                │
                                                                │    B/op    │    B/op     vs base                  │
Table_findnodeByID/SmallTable_5Results_NoPreferLive-10            248.0 ± 0%   248.0 ± 0%        ~ (p=1.000 n=10) ¹
Table_findnodeByID/SmallTable_16Results_NoPreferLive-10           376.0 ± 0%   376.0 ± 0%        ~ (p=1.000 n=10) ¹
Table_findnodeByID/SmallTable_5Results_PreferLive_AllLive-10      368.0 ± 0%   248.0 ± 0%  -32.61% (p=0.000 n=10)
Table_findnodeByID/SmallTable_16Results_PreferLive_AllLive-10     624.0 ± 0%   376.0 ± 0%  -39.74% (p=0.000 n=10)
Table_findnodeByID/SmallTable_5Results_PreferLive_HalfLive-10     368.0 ± 0%   248.0 ± 0%  -32.61% (p=0.000 n=10)
Table_findnodeByID/SmallTable_16Results_PreferLive_HalfLive-10    624.0 ± 0%   376.0 ± 0%  -39.74% (p=0.000 n=10)
Table_findnodeByID/MediumTable_5Results_NoPreferLive-10           248.0 ± 0%   248.0 ± 0%        ~ (p=1.000 n=10) ¹
Table_findnodeByID/MediumTable_16Results_NoPreferLive-10          376.0 ± 0%   376.0 ± 0%        ~ (p=1.000 n=10) ¹
Table_findnodeByID/MediumTable_5Results_PreferLive_AllLive-10     368.0 ± 0%   248.0 ± 0%  -32.61% (p=0.000 n=10)
Table_findnodeByID/MediumTable_16Results_PreferLive_AllLive-10    624.0 ± 0%   376.0 ± 0%  -39.74% (p=0.000 n=10)
Table_findnodeByID/MediumTable_5Results_PreferLive_HalfLive-10    368.0 ± 0%   248.0 ± 0%  -32.61% (p=0.000 n=10)
Table_findnodeByID/MediumTable_16Results_PreferLive_HalfLive-10   624.0 ± 0%   376.0 ± 0%  -39.74% (p=0.000 n=10)
Table_findnodeByID/LargeTable_5Results_NoPreferLive-10            248.0 ± 0%   248.0 ± 0%        ~ (p=1.000 n=10) ¹
Table_findnodeByID/LargeTable_16Results_NoPreferLive-10           376.0 ± 0%   376.0 ± 0%        ~ (p=1.000 n=10) ¹
Table_findnodeByID/LargeTable_5Results_PreferLive_AllLive-10      368.0 ± 0%   248.0 ± 0%  -32.61% (p=0.000 n=10)
Table_findnodeByID/LargeTable_16Results_PreferLive_AllLive-10     624.0 ± 0%   376.0 ± 0%  -39.74% (p=0.000 n=10)
Table_findnodeByID/LargeTable_5Results_PreferLive_HalfLive-10     368.0 ± 0%   248.0 ± 0%  -32.61% (p=0.000 n=10)
Table_findnodeByID/LargeTable_16Results_PreferLive_HalfLive-10    624.0 ± 0%   376.0 ± 0%  -39.74% (p=0.000 n=10)
Table_findnodeByID/FullTable_5Results_NoPreferLive-10             248.0 ± 0%   248.0 ± 0%        ~ (p=1.000 n=10) ¹
Table_findnodeByID/FullTable_16Results_NoPreferLive-10            376.0 ± 0%   376.0 ± 0%        ~ (p=1.000 n=10) ¹
Table_findnodeByID/FullTable_5Results_PreferLive_AllLive-10       368.0 ± 0%   248.0 ± 0%  -32.61% (p=0.000 n=10)
Table_findnodeByID/FullTable_16Results_PreferLive_AllLive-10      624.0 ± 0%   376.0 ± 0%  -39.74% (p=0.000 n=10)
geomean                                                           406.8        305.4       -24.93%
¹ all samples are equal

                                                                │   old.txt   │               new.txt                │
                                                                │  allocs/op  │ allocs/op   vs base                  │
Table_findnodeByID/SmallTable_5Results_NoPreferLive-10             6.000 ± 0%   6.000 ± 0%        ~ (p=1.000 n=10) ¹
Table_findnodeByID/SmallTable_16Results_NoPreferLive-10            7.000 ± 0%   7.000 ± 0%        ~ (p=1.000 n=10) ¹
Table_findnodeByID/SmallTable_5Results_PreferLive_AllLive-10      10.000 ± 0%   6.000 ± 0%  -40.00% (p=0.000 n=10)
Table_findnodeByID/SmallTable_16Results_PreferLive_AllLive-10     12.000 ± 0%   7.000 ± 0%  -41.67% (p=0.000 n=10)
Table_findnodeByID/SmallTable_5Results_PreferLive_HalfLive-10     10.000 ± 0%   6.000 ± 0%  -40.00% (p=0.000 n=10)
Table_findnodeByID/SmallTable_16Results_PreferLive_HalfLive-10    12.000 ± 0%   7.000 ± 0%  -41.67% (p=0.000 n=10)
Table_findnodeByID/MediumTable_5Results_NoPreferLive-10            6.000 ± 0%   6.000 ± 0%        ~ (p=1.000 n=10) ¹
Table_findnodeByID/MediumTable_16Results_NoPreferLive-10           7.000 ± 0%   7.000 ± 0%        ~ (p=1.000 n=10) ¹
Table_findnodeByID/MediumTable_5Results_PreferLive_AllLive-10     10.000 ± 0%   6.000 ± 0%  -40.00% (p=0.000 n=10)
Table_findnodeByID/MediumTable_16Results_PreferLive_AllLive-10    12.000 ± 0%   7.000 ± 0%  -41.67% (p=0.000 n=10)
Table_findnodeByID/MediumTable_5Results_PreferLive_HalfLive-10    10.000 ± 0%   6.000 ± 0%  -40.00% (p=0.000 n=10)
Table_findnodeByID/MediumTable_16Results_PreferLive_HalfLive-10   12.000 ± 0%   7.000 ± 0%  -41.67% (p=0.000 n=10)
Table_findnodeByID/LargeTable_5Results_NoPreferLive-10             6.000 ± 0%   6.000 ± 0%        ~ (p=1.000 n=10) ¹
Table_findnodeByID/LargeTable_16Results_NoPreferLive-10            7.000 ± 0%   7.000 ± 0%        ~ (p=1.000 n=10) ¹
Table_findnodeByID/LargeTable_5Results_PreferLive_AllLive-10      10.000 ± 0%   6.000 ± 0%  -40.00% (p=0.000 n=10)
Table_findnodeByID/LargeTable_16Results_PreferLive_AllLive-10     12.000 ± 0%   7.000 ± 0%  -41.67% (p=0.000 n=10)
Table_findnodeByID/LargeTable_5Results_PreferLive_HalfLive-10     10.000 ± 0%   6.000 ± 0%  -40.00% (p=0.000 n=10)
Table_findnodeByID/LargeTable_16Results_PreferLive_HalfLive-10    12.000 ± 0%   7.000 ± 0%  -41.67% (p=0.000 n=10)
Table_findnodeByID/FullTable_5Results_NoPreferLive-10              6.000 ± 0%   6.000 ± 0%        ~ (p=1.000 n=10) ¹
Table_findnodeByID/FullTable_16Results_NoPreferLive-10             7.000 ± 0%   7.000 ± 0%        ~ (p=1.000 n=10) ¹
Table_findnodeByID/FullTable_5Results_PreferLive_AllLive-10       10.000 ± 0%   6.000 ± 0%  -40.00% (p=0.000 n=10)
Table_findnodeByID/FullTable_16Results_PreferLive_AllLive-10      12.000 ± 0%   7.000 ± 0%  -41.67% (p=0.000 n=10)
geomean                                                            9.051        6.481       -28.40%
¹ all samples are equal

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant